package van.planifolia.dynamicproxy;

import van.planifolia.util.MakeLog;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by Intellij IDEA<br>
 *
 * @author Planifolia.Van
 * @version 1.0
 * @date 2022/11/9 17:35
 */
public class JDKProxy {
    private Computer computer;

    public JDKProxy(Computer computer) {
        this.computer = computer;
    }

    /**
     * 获取代理类对象的方法
     *
     * @return 代理类对象
     */
    public Computer getProxyBean() {
        // 我们要在内部实现这个接口来完成对被代理类中的每个方法的增强
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 运算前增强
                check(method, args);
                // 运算
                Integer result = (Integer) method.invoke(computer, args);
                // 运算后增强
                doLog(method, args, result);
                return result;
            }
        };
        // 然后我们要制作代理对象使用Proxy类中的方法
        // 根据参数他需要一个是类加载器，一个是接口的反射对象数组,还有一个我们之前写的方法回调适配器
        ClassLoader classLoader = computer.getClass().getClassLoader();
        Class<?>[] interfaces = computer.getClass().getInterfaces();
        return (Computer) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
    }

    /**
     * 计算前减产
     *
     * @param method 被检查的方法对象
     * @param args   被检查的方法参数
     */
    private void check(Method method, Object[] args) {
        if (method.getName().equals("divide")) {
            Integer integer = (Integer) args[1];
            if (integer == 0) {
                throw new RuntimeException("被除数不得为0");
            }
        }
        System.out.println("校验通过");
    }

    /**
     * 打日志的方法
     *
     * @param method 当前的方法
     * @param args   当前方法的参数组
     * @param result 当前方法的返回值
     */
    private void doLog(Method method, Object[] args, Integer result) {
        String name = method.getName();
        Integer t1 = (Integer) args[0];
        Integer t2 = (Integer) args[1];
        MakeLog.makeLog(t1 + " " + name + " " + t2 + " = " + result);
    }
}
